home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 363_01 / eval.c < prev    next >
C/C++ Source or Header  |  1991-09-23  |  15KB  |  498 lines

  1. /***********************************************************************
  2.  *
  3.  *      EVAL.C
  4.  *      Expression Evaluator for 68020 Assembler
  5.  *
  6.  *    Function: eval()
  7.  *      Evaluates a constant expression. The p argument points to the string
  8.  *      to be evaluated, and the function returns a pointer to the first
  9.  *      character beyond the end of the expression. The value of the
  10.  *      expression and an error code are returned via output arguments. The
  11.  *      function handles errors according to the following table:
  12.  *
  13.  *                         Pass1        Pass1   Pass2         Pass2
  14.  *      Condition          Error        *refPtr Error         *refPtr
  15.  *      ----------------   ----------   -----   -----------   -----
  16.  *      Undefined symbol   INCOMPLETE   FALSE   UNDEFINED     FALSE
  17.  *      Division by zero   INCOMPLETE   FALSE   DIV_BY_ZERO   FALSE
  18.  *      Syntax error       SYNTAX       --      SYNTAX        --
  19.  *      Constant error     x_TOO_BIG    T/F     x_TOO_BIG     T/F
  20.  *      No error           OK           T/F     OK            T/F
  21.  *
  22.  *      The char pointed to by refPtr is set to TRUE if all the symbols 
  23.  *      encountered in the expression are backwards references or FALSE if 
  24.  *      at least one symbol is a forward reference.
  25.  *
  26.  *   Usage: char *eval(char *p, long *valuePtr, char *refPtr, int *errorPtr)
  27.  *
  28.  *  Errors: ASCII_TOO_BIG
  29.  *          DIV_BY_ZERO
  30.  *          INCOMPLETE
  31.  *          NUMBER_TOO_BIG
  32.  *          REG_LIST_SPEC
  33.  *          SYNTAX
  34.  *          UNDEFINED
  35.  *
  36.  *      Author: Paul McKee
  37.  *      ECE492    North Carolina State University, 9/24/86
  38.  *
  39.  *      Modified A.E. Romer. Version 1.0
  40.  *          16 March 1991 - converted to ANSI, braces layout.
  41.  *          21 March 1991 - '.' disallowed in symbols except as first char.
  42.  *                          (to allow .w and .l suffixes in absolute
  43.  *                          addressing), '_' allowed as first character.
  44.  *          22 May 1991   - any character that is not valid in an expression
  45.  *                          is now the terminator.
  46.  *          Sept. 1991    - '$' disallowed in symbols.
  47.  ************************************************************************/
  48.  
  49.  
  50. #include <stdio.h>
  51. #include <ctype.h>
  52. #include "asm.h"
  53.  
  54. extern char pass2;
  55.  
  56. /* Largest number that can be represented in an unsigned int
  57.     - MACHINE DEPENDENT */
  58.  
  59. #define     INTLIMIT    0xFFFF
  60. #define     LONGLIMIT   0xFFFFFFFF
  61.  
  62. #define     STACKMAX    5
  63.  
  64.  
  65. char    *evalNumber(char *p, long *numberPtr, char *refPtr, int *errorPtr)
  66.     {
  67.     int status;
  68.     long base;
  69.     long x;
  70.     char name[SIGCHARS+1];
  71.     symbolDef *symbol;
  72.     int i;
  73.     char endFlag;
  74.  
  75.     *refPtr = TRUE;
  76.     if (*p == '-')
  77.         {
  78.         /* Evaluate unary minus operator recursively */
  79.  
  80.         p = evalNumber(++p, &x, refPtr, errorPtr);
  81.         *numberPtr = -x;
  82.         return p;
  83.         }
  84.     else if (*p == '~')
  85.         {
  86.         /* Evaluate one's complement operator recursively */
  87.  
  88.         p = evalNumber(++p, &x, refPtr, errorPtr);
  89.         *numberPtr = ~x;
  90.         return p;
  91.         }
  92.     else if (*p == '(')
  93.         {
  94.         /* Evaluate parenthesized expressions recursively */
  95.  
  96.         p = eval(++p, &x, refPtr, errorPtr);
  97.         if (*errorPtr > SEVERE)
  98.             return NULL;
  99.         else if (*p != ')')
  100.             {
  101.             NEWERROR(*errorPtr, SYNTAX);
  102.             return NULL;
  103.             }
  104.         else
  105.             {
  106.             *numberPtr = x;
  107.             return ++p;
  108.             }
  109.         }
  110.     else if (*p == '$' && isxdigit(*(p+1)))
  111.         {
  112.         /* Convert hex digits until another character is
  113.            found. (At least one hex digit is present.) */
  114.  
  115.         x = 0;
  116.         while (isxdigit(*++p))
  117.             {
  118.             if ((unsigned long)x > (unsigned long)LONGLIMIT/16)
  119.                 NEWERROR(*errorPtr, NUMBER_TOO_BIG);
  120.             if (*p > '9')
  121.                 x = 16 * x + (*p - 'A' + 10);
  122.             else
  123.                 x = 16 * x + (*p - '0');
  124.             }
  125.         *numberPtr = x;
  126.         return p;
  127.         }
  128.     else if (*p == '%' || *p == '@' || isdigit(*p))
  129.         {
  130.         /* Convert digits in the appropriate base (binary,
  131.            octal, or decimal) until an invalid digit is found. */
  132.  
  133.         if (*p == '%')
  134.             {
  135.             base = 2;
  136.             p++;
  137.             }
  138.         else if (*p == '@')
  139.             {
  140.             base = 8;
  141.             p++;
  142.             }
  143.         else base = 10;
  144.  
  145.         /* Check that at least one digit is present */
  146.  
  147.         if (*p < '0' || *p >= '0' + base)
  148.             {
  149.             NEWERROR(*errorPtr, SYNTAX);
  150.             return NULL;
  151.             }
  152.         x = 0;
  153.  
  154.         /* Convert the digits into an integer */
  155.  
  156.         while (*p >= '0' && *p < '0' + base)
  157.             {
  158.             if (x > (LONGLIMIT - (*p - '0')) / base)
  159.                 {
  160.                 NEWERROR(*errorPtr, NUMBER_TOO_BIG);
  161.                 }
  162.             x = (long) ( (long) ((long) base * x) + (long) (*p - '0') );
  163.             p++;
  164.             }
  165.         *numberPtr = x;
  166.         return p;
  167.         }
  168.     else if (*p == CHAR_DELIMITER)
  169.         {
  170.         endFlag = FALSE;
  171.         i = 0;
  172.         x = 0;
  173.         p++;
  174.         while (!endFlag)
  175.             {
  176.             if (*p == CHAR_DELIMITER)
  177.                 if (*(p+1) == CHAR_DELIMITER)
  178.                     {
  179.                     x = (x << 8) + *p;
  180.                     i++;
  181.                     p++;
  182.                     }
  183.                 else
  184.                     endFlag = TRUE;
  185.             else
  186.                 {
  187.                 x = (x << 8) + *p;
  188.                 i++;
  189.                 }
  190.             p++;
  191.             }
  192.         if (i == 0)
  193.             {
  194.             NEWERROR(*errorPtr, SYNTAX);
  195.             return NULL;
  196.             }
  197.         else if (i == 3)
  198.             x = x << 8;
  199.         else if (i > 4)
  200.             NEWERROR(*errorPtr, ASCII_TOO_BIG);
  201.         *numberPtr = x;
  202.         return p;
  203.         }
  204.     else if (isalpha(*p) || *p == '.' || *p == '_')
  205.         {
  206.         /* Determine the value of a symbol */
  207.  
  208.         i = 0;
  209.         /* Collect characters of the symbol's name
  210.            (only SIGCHARS characters are significant) */
  211.  
  212.         do
  213.             {
  214.             if (i < SIGCHARS)
  215.                 name[i++] = *p;
  216.             p++;
  217.             } while (isalnum(*p) || *p == '_' || *p == '$');
  218.         name[i] = '\0';
  219.         /* Look up the name in the symbol table, resulting
  220.            in a pointer to the symbol table entry */
  221.  
  222.         status = OK;
  223.         symbol = lookup(name, &status);
  224.  
  225. /*      printf("EvalNumber: Status from lookup = %04X\n", status); */
  226.  
  227.         if (status == OK)
  228.             /* If symbol was found, and it's not a register
  229.                list symbol, then return its value */
  230.  
  231.             if (!(symbol->flags & REG_LIST_SYM))
  232.                 {
  233.                 *numberPtr = symbol->value;
  234.  
  235. /*              printf("The value of the symbol \"%s\" is %08lX\n",
  236.                     name, *numberPtr); */
  237.  
  238.                 if (pass2)
  239.                     *refPtr = (symbol->flags & BACKREF);
  240.                 }
  241.             else
  242.                 {
  243.                 /* If it is a register list symbol, return error */
  244.  
  245.                 *numberPtr = 0;
  246.                 NEWERROR(*errorPtr, REG_LIST_SPEC);
  247.                 }
  248.         else
  249.             {
  250.             /* Otherwise return an error */
  251.  
  252.             if (pass2)
  253.                 {
  254.                 NEWERROR(*errorPtr, UNDEFINED);
  255.                 }
  256.             else
  257.                 NEWERROR(*errorPtr, INCOMPLETE);
  258.             *refPtr = FALSE;
  259.             }
  260.  
  261. /*      printf("The symbol \"%s\" is%s a backwards reference\n",
  262.             name, (*refPtr) ? "" : " not"); */
  263.  
  264.         return p;
  265.         }
  266.     else
  267.         {
  268.         /* Otherwise, the character was not a valid operand */
  269.  
  270.         NEWERROR(*errorPtr, SYNTAX);
  271.         return NULL;
  272.         }
  273.  
  274.     return NORMAL;
  275.     }
  276.  
  277.  
  278.  
  279. int precedence(char op)
  280.     {
  281.     /* Compute the precedence o